#include <stdio.h>
#include <stdlib.h>

#include "objects.h"
#include "ports.h"

port port_table[100];
port empty_port;

void
init_port_table(void)
{
	scm i;

	empty_port = (port){ .tag = PORT_EMPTY };

	for(i = 0; i < 100; ++i) {
		port_table[i] = empty_port;
	}
}

scm
next_port(void)
{
	scm i = 0;

	for(i = 0; i < 100; ++i) {
		if(port_table[i].tag == PORT_EMPTY)
			return i;
	}
	
	fprintf(stderr, "Error: no free ports\n");
	exit(1);
}

scm
mk_port(FILE *f)
{
	scm p = next_port();

	port_table[p].tag = PORT_FILE;
	port_table[p].body.port = f;

	return mk_prt(p);
}

scm
mk_pipe(FILE *f, FILE *g)
{
	scm p = next_port();

	port_table[p].tag = PORT_PIPE;
	port_table[p].body.pipe[0] = f;
	port_table[p].body.pipe[1] = g;

	return mk_prt(p);
}

FILE*
port_get_file(scm p)
{
	port f = port_table[get_prt(p)];
	switch(f.tag) {
	case PORT_EMPTY:
		fprintf(stderr, "Error: Attempted to dereference an empty port\n");
		exit(1);
		return NULL;
	case PORT_FILE:
		return f.body.port;
	case PORT_PIPE:
		return f.body.pipe[0];
	}

	exit(1);
	return NULL;
}

FILE*
port_get_pipe_end(scm p)
{
	port f = port_table[get_prt(p)];
	assert(f.tag == PORT_PIPE);
	return f.body.pipe[1];
}

int
port_empty(scm p)
{
	port f = port_table[get_prt(p)];
	return (f.tag == PORT_EMPTY);
}


void
port_close(scm s)
{
	scm i = get_prt(s);
	port p = port_table[i];
	
	switch (p.tag) {
	case PORT_EMPTY:
		fprintf(stderr, "Error: attempted to close an empty port\n");
		exit(1);
		break;
	case PORT_FILE:
		fclose(p.body.port);
		break;
	case PORT_PIPE:
		fclose(p.body.pipe[0]);
		fclose(p.body.pipe[1]);
		break;
	}
	
	port_table[i].tag = PORT_EMPTY;
}


